package com.coderush.admin.sys.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.alibaba.fastjson2.JSON;

import com.coderush.admin.core.component.JwtUtil;
import com.coderush.admin.core.component.RedisClient;
import com.coderush.admin.core.utils.UserContext;
import com.coderush.admin.core.utils.UserContextModel;
import com.coderush.admin.sys.consts.EmployeeCacheKey;
import com.coderush.admin.sys.dao.LoginDao;
import com.coderush.admin.sys.exception.LoginException;
import com.coderush.admin.sys.model.cache.EmployeeInfoCacheModel;
import com.coderush.admin.sys.model.dto.LoginDto;
import com.coderush.admin.sys.model.entity.Employee;
import com.coderush.admin.sys.model.vo.UserRoleVo;
import com.coderush.admin.sys.model.vo.VerifyCodeVo;
import com.coderush.admin.sys.service.LoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * PackageName com.stellarforce.admin.sys.service.impl
 *
 * @Author Eason
 * @Version v1.0
 * @ClassName LoginServiceImpl
 * @Date 2025/8/18
 * @Description TODO
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class LoginServiceImpl implements LoginService {

    private final LoginDao loginDao;

    private final PasswordEncoder passwordEncoder;

    private final JwtUtil jwtUtil;

    private final RedisClient redisClient;

    /**
     * 获取验证码
     * @return
     */
    @Override
    public VerifyCodeVo getVerifyCode() {

        // 使用hutool工具包中的工具类生成图片验证码
        //参数：宽  高  验证码位数 干扰线数量
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 20);
        String codeValue = circleCaptcha.getCode();
        String imageBase64 = circleCaptcha.getImageBase64();

        // 生成uuid作为图片验证码的key
        String codeKey = UUID.randomUUID().toString().replace("-", "");

        // 将验证码存储到Redis中
        redisClient.setKVWithTime(EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_VERIFY_CODE_KEY + codeKey
                                                , codeValue , EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_VERIFY_CODE_TIMEOUT);

        // 返回验证码
        VerifyCodeVo verifyCodeVo = new VerifyCodeVo();
        verifyCodeVo.setCodeKey(codeKey);
        verifyCodeVo.setImageBase64("data:image/png;base64," + imageBase64);

        return verifyCodeVo;
    }

    @Override
    public String login(LoginDto loginDto) {

        // 登录验证码对比
        // 从缓存中获取登录验证码
        String verifyCode = (String) redisClient.getKV(EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_VERIFY_CODE_KEY + loginDto.getVerifyCodeKey());
        if (verifyCode == null) {
            // 验证码不存在
            throw LoginException.verifyCodeNotExist();
        }
        verifyCode = verifyCode.toLowerCase();
        // 验证码错误
        if (!verifyCode.equals(loginDto.getVerifyCode().toLowerCase())) {
            throw LoginException.verifyCodeError();
        }

        Employee employeeDb = null;

        // 判断当前的登录账号是手机号还是其他的
        if (!loginDto.getLoginAccount().matches("^1[3-9]\\d{9}$")) {
            // login_name 登录账号，登录
            employeeDb = loginDao.getEmployeeByLoginName(loginDto.getLoginAccount());
        }
        else {
            // 手机号登录
            employeeDb = loginDao.getEmployeeByPhone(loginDto.getLoginAccount());
        }

        if (employeeDb == null) {
            // 员工信息不存在
            throw LoginException.errorNameOrPassword();
        }

        // 密码对比
        if (!passwordEncoder.matches(loginDto.getPassword(), employeeDb.getPassword())) {
            // 密码错误
            throw LoginException.errorNameOrPassword();
        }

        // 查询员工对应的角色信息
        var userRoleList = loginDao.getUserRoleList(employeeDb.getId());

        // 生成accessToken
        String accessToken = jwtUtil.generateAccessToken(String.valueOf(employeeDb.getId()));

        // 构建用户上下文缓存
        UserContextModel userContextModel = new UserContextModel();
        userContextModel.setUserId(employeeDb.getId()); // 用户id
        userContextModel.setUsername(employeeDb.getEmpName()); // 用户名
        userContextModel.setCompanyId(employeeDb.getCompanyId()); // 公司id
        userContextModel.setUserRoleVoList(userRoleList); // 用户角色信息
        // 是否超级管理员
        if (!CollectionUtils.isEmpty(userRoleList)) {
            for (UserRoleVo userRole : userRoleList) {
                if (userRole.getRoleCode().equals("admin")) {
                    userContextModel.setIsAdmin(true);
                    userContextModel.setCompanyId(null); // 超级管理员的公司ID为null
                    break;
                }
            }
        }

        // 缓存用户上下文
        redisClient.setKVWithTime(EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_PREFIX + accessToken
                                            , userContextModel, EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_TIMEOUT);

        return accessToken;
    }

    /**
     * 登出
     */
    @Override
    public void logout() {

        UserContextModel user = UserContext.getUser();

        redisClient.delKV(EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_PREFIX + user.getAccessToken());
    }
}